<template>
  <div>
    <el-tree
      ref="treeRef"
      class="tree-data"
      :allow-drop="allowDrop"
      :data="sceneStore.layerTree"
      draggable
      :props="{
        class: getNodeClass,
      }"
      :default-expanded-keys="sceneStore.expandedKeys"
      node-key="fe_id"
      @node-drop="handleDragDrop"
      @check="check"
    >
      <template #default="{ node, data }">
        <div class="tree-node" @click="selectNode(node)">
          <div @click.stop>
            <el-checkbox
              v-if="!data.fe_deleted"
              v-model="data.fe_checked"
              :indeterminate="data.fe_indeterminate"
              @change="handleCheck(node, data)"
            ></el-checkbox>
          </div>
          <SvgIcon class="prefix-icon" :icon-class="getSvgClass(data)" />
          <span
            :class="data.fe_deleted ? 'deleted-label' : ''"
            :style="{ width: getLabelWidth(node) }"
            >{{ data.name }}</span
          >
          <span v-if="data.fe_deleted" class="deleted-icon">已删除</span>
          <div class="operate">
            <SvgIcon v-if="isLocation(data)" icon-class="ic_定位" @click="layerLocation(data)" />
            <SvgIcon
              v-if="!['building'].includes(data.type)"
              icon-class="ic_编辑2"
              @click.stop="selectLayer(data, $event)"
            />
            <SvgIcon
              v-if="!['building'].includes(data.type)"
              icon-class="ic_删除"
              @click.stop="deleteNode(data)"
            />
          </div>
        </div>
      </template>
    </el-tree>
  </div>
</template>

<script setup lang="ts">
import { deleteLayer } from '@/service/layer';
import { useStageStore } from '@/store/stage';
import { useSceneStore } from '@/store/scene';
import { confirmAgain } from '@/utils';
import type Node from 'element-plus/es/components/tree/src/model/node';
import type { DragEvents } from 'element-plus/es/components/tree/src/model/useDragNode';
import type { AllowDropType, NodeDropType } from 'element-plus/es/components/tree/src/tree.type';

defineOptions({
  name: 'LayerTree',
});

let currSelLayer = null as any;
const stageStore = useStageStore();
const sceneStore = useSceneStore();
const treeRef = ref<any>();

interface IProps {
  isLocation: Function;
}

const props = withDefaults(defineProps<IProps>(), {
  isLocation: () => {},
});

const emits = defineEmits(['loaction', 'selectLayer']);

const getNodeClass = (data: any, node: any) => {
  if (data.fe_id === sceneStore.selectedLayerNode?.data.fe_id) {
    return 'selected-node';
  }
  return '';
};

const getSvgClass = (data: any) => {
  if (data.type === 'folder') {
    return '文件夹';
  }
  return 'cube';
};

const getLabelWidth = (node: any) => {
  const data = node.data;
  let width = 0;
  if (!data.fe_deleted) {
    width = 220 - node.level * 25;
    return width + 'px';
  }
  // 被删除
  return width - 65 + 'px';
};

onMounted(async () => {
  if (sceneStore.selectedLayerNode) {
    sceneStore.selLayer = sceneStore.selectedLayerNode.data;
    selectLayer(sceneStore.selLayer, null);
  } else {
    if (sceneStore.layerTree.length > 0) {
      sceneStore.selLayer = sceneStore.layerTree[0];
      selectLayer(sceneStore.layerTree[0], null);
    }
  }
});

onBeforeUnmount(() => {
  sceneStore.specialEffectVisible = false;
  sceneStore.selLayer = null;
  currSelLayer = null;
  // 销毁前默认保存要展开的节点id
  const expandedNodeIds: any = [];
  getAllExpandedNodes(treeRef.value.root.childNodes, expandedNodeIds);
  sceneStore.expandedKeys = expandedNodeIds;
});

function getAllExpandedNodes(nodes: Node[], result: any[]) {
  nodes.forEach((node: Node) => {
    if (node.expanded) {
      result.push(node.data.fe_id);
    }
    if (node.childNodes?.length > 0) {
      getAllExpandedNodes(node.childNodes, result);
    }
  });
}

const allowDrop = (draggingNode: Node, dropNode: Node, type: AllowDropType) => {
  if (dropNode.data.type !== 'folder') {
    return false;
  } else {
    return true;
  }
};

const handleDragDrop = (
  draggingNode: Node,
  dropNode: Node,
  dropType: NodeDropType,
  ev: DragEvents
) => {
  dropNode.expanded = true;
  dropNode.childNodes.forEach((ele: Node) => {
    if (ele.data.fe_id === draggingNode.data.fe_id) {
      // ToDo ele.checked = draggingNode.checked;
      ele.data.fe_checked = draggingNode.data.fe_checked;
    }
  });
  if (dropNode.childNodes.every((ele) => ele.data.fe_checked === true)) {
    dropNode.data.fe_checked = true;
  } else if (dropNode.childNodes.every((ele) => ele.data.fe_checked === false)) {
    dropNode.data.fe_checked = false;
  } else {
    dropNode.data.fe_indeterminate = true;
  }
  if (dropType === 'inner') {
    draggingNode.data.fe_parentId = dropNode.data.fe_id;
  } else {
    const parent = dropNode.parent;
    if (parent.level === 0) {
      draggingNode.data.fe_parentId = '';
    } else {
      draggingNode.data.fe_parentId = parent.data.fe_id;
    }
  }
};

// 树结构勾选
const check = (currNode: Node, selectedObj: any) => {
  const showLayerCodes =
    selectedObj.checkedNodes
      .filter((node: any) => node.type !== 'folder')
      .map((item: any) => item.code) || [];
  sceneStore.layerList.forEach((list: any) => {
    if (!showLayerCodes.includes(list.code)) {
      list.show = false;
    } else {
      list.show = true;
    }
  });
};

// 删除节点
const deleteNode = async (data: any) => {
  currSelLayer = data;
  currSelLayer = data;
  const text =
    data.type === 'folder'
      ? `${data.name}以及该文件夹下所有素材将被删除！您确定要删除XX文件夹?`
      : `您确定要删除${data.name}`;
  const flag = await confirmAgain('移除', text);
  if (!flag) return;
  const currNode = treeRef.value.getNode(data.fe_id);
  const deleteObj = {
    deleteNodes: [],
    deleteLayeList: [],
  };
  getDeletedNodes(currNode, deleteObj);
  deleteObj.deleteNodes.forEach((ele: any) => {
    if (sceneStore.selectedLayerNode && sceneStore.selectedLayerNode.data.fe_id === ele) {
      // 选中置空
      sceneStore.selectedLayerNode = null;
    }
    treeRef.value.remove(ele);
  });
  deleteObj.deleteLayeList.forEach((ele: any) => {
    deleteLayer(ele);
  });
};

// 获取要删除的节点数据和资源数据
function getDeletedNodes(
  currNode: Node,
  deleteObj: any = {
    deleteNodes: [],
    deleteLayeList: [],
  }
) {
  if (currNode.isLeaf) {
    if (currNode.data.type === 'folder') {
      deleteObj.deleteNodes.push(currNode.data.fe_id);
    } else {
      deleteObj.deleteLayeList.push(currNode.data);
      deleteObj.deleteNodes.push(currNode.data.fe_id);
    }
  } else {
    deleteObj.deleteNodes.push(currNode.data.fe_id);
    currNode.childNodes.forEach((ele: Node) => {
      getDeletedNodes(ele, deleteObj);
    });
  }
}

const layerLocation = (layer: API.Scene.ILayer) => {
  currSelLayer = layer;
  emits('loaction', layer);
};

// 选中节点
const selectNode = (node: Node) => {
  // TODO 临时复用旧版
  stageStore.layerId = node.data?.layerName as any;
  stageStore.rightVisible = true;

  sceneStore.selectedLayerNode = node;
  selectLayer(node.data as any, null);
};

const selectLayer = (layer: API.Scene.ILayer, event: any) => {
  const node = treeRef.value.getNode((layer as any).fe_id);
  sceneStore.selectedLayerNode = node;
  event && event.stopPropagation();
  currSelLayer = layer;
  emits('selectLayer', layer);
};

const handleCheck = (node: Node, data: any) => {
  if (!node.isLeaf) {
    setCheckedAllChild(node, data.fe_checked);
  }
  setCheckedParentNodes(node, data.fe_checked);

  const checkedNodes: any = [];
  getCheckedNodes(sceneStore.layerTree, checkedNodes);
  check(node, { checkedNodes });
};

// 设置父节点的checked
const setCheckedParentNodes = (node: Node, flag: boolean) => {
  const parent = node.parent;
  if (parent && parent.level > 0) {
    if (parent.childNodes.every((ele: any) => ele.data.fe_checked === flag)) {
      parent.data.fe_checked = flag;
      parent.data.fe_indeterminate = false;
      if (parent.childNodes.some((ele: any) => ele.data.fe_indeterminate === true)) {
        parent.data.fe_indeterminate = true;
      }
    } else if (parent.childNodes.every((ele: any) => ele.data.fe_checked === !flag)) {
      parent.data.fe_checked = !flag;
      parent.data.fe_indeterminate = false;
      if (parent.childNodes.some((ele: any) => ele.data.fe_indeterminate === true)) {
        parent.data.fe_indeterminate = true;
      }
    } else {
      parent.data.fe_checked = true;
      parent.data.fe_indeterminate = true;
    }
    setCheckedParentNodes(parent, flag);
  }
};

// 更新child的checked
const setCheckedAllChild = (node: Node, flag: boolean) => {
  node.data.fe_checked = flag;
  node.data.fe_indeterminate = false;
  if (node.childNodes.length > 0) {
    node.childNodes.forEach((ele: Node) => {
      setCheckedAllChild(ele, flag);
    });
  }
};

// 获取已勾选的节点
const getCheckedNodes = (nodes: Node[], arr: any) => {
  if (nodes.length) {
    nodes.forEach((ele: any) => {
      if (ele.fe_checked) {
        arr.push(ele);
      }
      if (ele.children && ele.children.length > 0) {
        getCheckedNodes(ele.children, arr);
      }
    });
  }
};
</script>

<style lang="less" scoped>
.tree-data {
  background: #0a0b0d;
  padding: 0 10px;
  margin-top: 10px;

  :deep(.selected-node > .el-tree-node__content) {
    background-color: rgba(5, 96, 253, 0.2);
    border-radius: 4px;
    border: 1px solid #0560fd;
  }

  :deep(.el-tree-node__content) {
    border: 1px solid #0a0b0d;
  }

  .tree-node {
    display: flex;
    align-items: center;
    width: 100%;
    margin-left: 27px;

    .expand-icon {
      margin-left: 10px;
      .svg-icon {
        transition: transform 0.4s ease-out;
        transform: rotate(180deg);
      }
    }

    .prefix-icon {
      font-size: 20px;

      &.deleted-icon {
        color: #9a9a9a;
      }
    }
    span {
      margin-left: 5px;
      font-size: 14px;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 500;
      color: #ffffff;
      max-width: calc(100% - 150px);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .deleted-label {
      color: #9a9a9a;
      font-weight: 400;
    }

    .deleted-icon {
      background: #ff5454;
      border-radius: 4px;
      width: 48px;
      height: 20px;
      line-height: 20px;
      text-align: center;
      font-size: 12px;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 500;
      color: #ffffff;
      margin-left: 10px;
    }

    .operate {
      margin-left: auto;
      display: flex;
      align-items: center;
      margin-right: 5px;
      .svg-icon {
        font-size: 20px;
        margin-right: 4px;
        &:last-child {
          margin-right: 0px;
        }
      }
    }
  }

  :deep(.el-tree-node__content:hover) {
    background-color: rgba(5, 96, 253, 0.2);
  }

  :deep(.el-tree-node:focus > .el-tree-node__content) {
    background-color: rgba(5, 96, 253, 0.2);
    // border-radius: 4px;
    // border: 1px solid #0560fd;
  }

  // 选择框在前
  :deep(.el-tree-node__content) {
    position: relative;
    margin-top: 14px;
  }

  :deep(.tree-node .el-checkbox) {
    position: absolute;
    left: 9px;
    top: -4px;

    .el-checkbox__inner {
      background: #2b3139;
      border-radius: 2px;
      border-color: #454851;
    }

    .el-checkbox__input.is-checked .el-checkbox__inner {
      background: #0560fd;
      border-radius: 3px;
    }
  }

  :deep(.el-tree-node > .el-tree-node__content > .el-tree-node__expand-icon.is-leaf) {
    display: none;
  }

  :deep(.el-tree-node__content > .el-tree-node__expand-icon) {
    margin-left: 25px;
    font-size: 14px;
  }

  :deep(.el-tree-node__content) {
    .el-tree-node__expand-icon.is-leaf {
      & + .tree-node {
        margin-left: 27px;

        .prefix-icon {
          margin-left: 2px;
        }
      }
    }
    .el-tree-node__expand-icon {
      & + .tree-node {
        margin-left: 0;
      }
    }
  }
}
</style>
